// SPDeployExt.cpp : Implementation of CSPDeployExt

#include "stdafx.h"
#include "SPDeployExt.h"
#include <atlconv.h>

using namespace std;

// CSPDeployExt

HRESULT CSPDeployExt::Initialize(LPCITEMIDLIST pidlFolder, 
						LPDATAOBJECT pDataObj, 
						HKEY hProgID)
{
	FORMATETC fmt = {CF_HDROP, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL};
	STGMEDIUM stg = {TYMED_HGLOBAL};
	HDROP hDrop;

	if (FAILED(pDataObj->GetData(&fmt, &stg)))
		return E_INVALIDARG;

	hDrop = (HDROP)GlobalLock(stg.hGlobal);

	if (NULL == hDrop)
		return E_INVALIDARG;

	UINT uNumFiles = DragQueryFile(hDrop, 0xFFFFFFFF, NULL, 0);
	HRESULT hr = S_OK;

	if (0 == uNumFiles)
	{
		GlobalUnlock(stg.hGlobal);
		ReleaseStgMedium(&stg);
		return E_INVALIDARG;
	}

	if (0 == DragQueryFile(hDrop, 0, _fileName, MAX_PATH))
		hr = E_INVALIDARG;

	GlobalUnlock(stg.hGlobal);
	ReleaseStgMedium(&stg);
	
	return hr;
}

HRESULT CSPDeployExt::QueryContextMenu(HMENU hmenu, 
									   UINT uMenuIndex, 
									   UINT	uidFirstCmd, 
									   UINT uidLastCmd, 
									   UINT uFlags)
{
	if (uFlags & CMF_DEFAULTONLY)
		return MAKE_HRESULT(SEVERITY_SUCCESS, FACILITY_NULL, 0);
	
	//	Create sub menu for deployment items
	HMENU subMenu = CreatePopupMenu();
	UINT uID = uidFirstCmd;

	//	Create sub menu items
	InsertMenu(subMenu, 0, MF_BYPOSITION, uID++, 
		_T("Add Solution to Local SharePoint Server"));
	InsertMenu(subMenu, 1, MF_BYPOSITION, uID++, 
		_T("Upgrade Solution on Local SharePoint Server"));
	InsertMenu(subMenu, 2, MF_BYPOSITION, uID++, 
		_T("Deploy Solution on Local SharePoint Server"));
	InsertMenu(subMenu, 3, MF_BYPOSITION, uID++, 
		_T("Add and Deploy Solution to Local SharePoint Server"));

	//	Add sub menu to context menu
	MENUITEMINFO itemInfo = {sizeof(MENUITEMINFO)};
	itemInfo.fMask = MIIM_SUBMENU | MIIM_STRING | MIIM_ID;
	itemInfo.wID = uID++;
	itemInfo.hSubMenu = subMenu;
	itemInfo.dwTypeData = _T("SharePoint Deployment");
	InsertMenuItem(hmenu, uMenuIndex, TRUE, &itemInfo);

	return MAKE_HRESULT(SEVERITY_SUCCESS, FACILITY_NULL, uID - uidFirstCmd);
}

HRESULT CSPDeployExt::GetCommandString(UINT_PTR idCmd, 
									   UINT uFlags, 
									   UINT* pwReserved, 
									   LPSTR pszName, 
									   UINT cchMax)
{
	USES_CONVERSION;

	if (0 != idCmd)
		return E_INVALIDARG;

	if (uFlags & GCS_HELPTEXT)
	{
		LPCTSTR helpText = _T("Deploys the selected file to the local SharePoint Server");

		if (uFlags & GCS_UNICODE)
		{
			lstrcpynW((LPWSTR)pszName, T2CW(helpText), cchMax);
		}
		else
		{
			lstrcpynA(pszName, T2CA(helpText), cchMax);
		}

		return S_OK;
	}

	return E_INVALIDARG;
}

HRESULT CSPDeployExt::InvokeCommand(LPCMINVOKECOMMANDINFO pCmdInfo)
{
	if (0 != HIWORD(pCmdInfo->lpVerb))
		return E_INVALIDARG;

	DeploySolutionFile(_fileName, LOWORD(pCmdInfo->lpVerb));
	return S_OK;
}

void CSPDeployExt::DeploySolutionFile(TCHAR fileName[MAX_PATH], UINT actionInvoked)
{
	/*MessageBox(hwnd, fileName, _T("SPDeploy: Deploy SharePoint Solution File"), 
		MB_ICONINFORMATION);*/
	
	//	Create strings containing command to execute and it's parameters.
	wstring command = L"C:\\Windows\\System32\\cmd.exe"; 
	wstring cmdArg = L" /K ";
	wstring workingDirectory = 
		L"C:\\Program Files\\Common Files\\Microsoft Shared\\Web Server Extensions\\12\\BIN\\";
	wstring stsadmCommand = L"\"\STSADM.EXE ";
	wstring cmdArgs;

	switch (actionInvoked)
	{
		case Action::AddSolution:
		case Action::AddAndDeploySolution:
			cmdArgs = GetAddSolutionArgs(fileName);
			break;

		case Action::UpgradeSolution:
			cmdArgs = GetUpgradeSolutionArgs(fileName);
			break;

		case Action::DeploySolution:
			cmdArgs = GetDeploySolutionArgs(fileName);
			break;
	}

	wstring fullCmdArgs = cmdArg + stsadmCommand + cmdArgs;

	//	Execute command.
	ShellExecute(NULL, L"Open", command.c_str(), fullCmdArgs.c_str(), 
		workingDirectory.c_str(), SW_SHOWNORMAL);

	if (Action::AddAndDeploySolution == actionInvoked)
	{
		ShellExecute(NULL, L"Open", command.c_str(), GetDeploySolutionArgs(fileName).c_str(), 
		workingDirectory.c_str(), SW_SHOWNORMAL);
	}
}

wstring CSPDeployExt::GetAddSolutionArgs(TCHAR fileName[MAX_PATH])
{
	wstring stsadmOperation = L"-o addsolution ";
	wstring fileNameArg = L"-filename ";
	wstring fileNameString = fileName;
	wstring cmdArgs = stsadmOperation + fileNameArg + fileNameString;

	return cmdArgs;
}

wstring CSPDeployExt::GetUpgradeSolutionArgs(TCHAR fileName[MAX_PATH])
{
	wstring stsadmOperation = L"-o upgradesolution ";
	wstring fileNameArg = L"-filename ";
	wstring solutionNameArg = L" -name ";
	wstring otherArgs = L" -immediate -allowgacdeployment -allowcaspolicies\"\"";
	wstring fileNameString = fileName;
	wstring solutionName = fileNameString.substr(fileNameString.find_last_of(L"\\") + 1, 
		(fileNameString.length() - (fileNameString.find_last_of(L"\\"))));
	wstring cmdArgs = stsadmOperation + fileNameArg + fileNameString + 
		solutionNameArg + solutionName + otherArgs;

	return cmdArgs;
}

wstring CSPDeployExt::GetDeploySolutionArgs(TCHAR fileName[MAX_PATH])
{
	wstring stsadmOperation = L"-o deploysolution ";
	wstring solutionNameArg = L" -name ";
	wstring otherArgs = L" -immediate -allcontenturls -allowgacdeployment -allowcaspolicies\"\"";
	wstring fileNameString = fileName;
	wstring solutionName = fileNameString.substr(fileNameString.find_last_of(L"\\") + 1, 
		(fileNameString.length() - (fileNameString.find_last_of(L"\\"))));
	wstring cmdArgs = stsadmOperation + solutionNameArg + solutionName + otherArgs;

	return cmdArgs;
}